﻿using System;
using System.Linq;
using System.IO;
using System.Management;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using Convertor.Interface;
using mshtml;
using Wpf.CommonTools.StaticExtension;
using Wpf.CommonTools.SystemExtension;
using Wpf.CommonTools.NumberExtension;
using System.Windows.Data;

namespace Convertor
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window, IPluginOutputHeler
    {
        private Thread threadOutput;
        private PopForm popForm;
        private System.Timers.Timer timer;
        private DateTime convertDuringTime;

        #region MainForm Function

        public MainWindow()
        {
            InitializeComponent();

            popForm = new PopForm(this);
            timer = new System.Timers.Timer();
            timer.Elapsed += timer_Elapsed;
            timer.Interval = 1000;

            ((IMyWindows)pluginControl).MyWindows = this;
            OutputFunc = new ConvertHelper();
            OutputFunc.Log = Log;
            OutputFunc.Elapsed += outputFunc_Elapsed;

        }

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            ((IPluginLog)pluginControl).Log = Log;
            if (!Config.SafeModel)
            {
                loadArgs(sender, e);
                checkUpdate();
            }
            //menuItem_ShowAbout_Click(this, null);
            //menuItem_Setting_Click(this, null);
            HideScriptErrors(wbOutput, true);
        }

        public void HideScriptErrors(WebBrowser wb, bool hide)
        {
            var fiComWebBrowser = typeof(WebBrowser).GetField("_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic);
            if (fiComWebBrowser == null) return;
            var objComWebBrowser = fiComWebBrowser.GetValue(wb);
            if (objComWebBrowser == null)
            {
                wb.Loaded += (o, s) => HideScriptErrors(wb, hide); //In case we are to early
                return;
            }
            objComWebBrowser.GetType().InvokeMember("Silent", BindingFlags.SetProperty, null, objComWebBrowser, new object[] { hide });
        }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            PluginHandler.SavePluginAsTemplateToDisk(Config.CurrentPlugin, true);
            stopOutputThread();
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.S && (Keyboard.Modifiers & (ModifierKeys.Control)) == (ModifierKeys.Control))
            {
                menuItem_SaveToTempalte_Click(this, new RoutedEventArgs());
                e.Handled = true;
            }
            else if ((e.Key == Key.R && (Keyboard.Modifiers & (ModifierKeys.Control)) == (ModifierKeys.Control)) || e.Key == Key.F5)
            {
                btOutput_Click(btOutput, e);
                e.Handled = true;
            }
            else if (e.Key == Key.N && (Keyboard.Modifiers & (ModifierKeys.Control)) == (ModifierKeys.Control))
            {
                initTemplate();
            }
        }

        #endregion

        #region Menu Function

        private void menuItem_OpenInputText_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

            dlg.DefaultExt = ".txt";
            dlg.Filter = "文本文件(*.txt, *.htm)|*.txt;*.htm;*.htm|所有文件(*.*)|*.*";
            if (dlg.ShowDialog() == true)
            {
                string filename = dlg.FileName;
                loadInputText(filename);
            }
        }

        private void menuItem_CloseApp_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void menuItem_SaveToTempalte_Click(object sender, RoutedEventArgs e)
        {
            string filename = Config.CurrentTemplate.Container.Name;
            if (Config.CurrentTemplate.Container.Path == Config.TempPluginsSavePath)
            {
                RenameWindow re = new RenameWindow(Config.CurrentTemplate.Container);
                re.SetCenterOfWindow(this);
                re.Activate();
                re.Topmost = true;
                if (re.ShowDialog() == true)
                {
                    string name = Config.CurrentTemplate.Container.Path;
                    bool save = true;
                    if (File.Exists(name))
                    {
                        save = MessageBox.Show(UILanguage.FindResource("SaveTemplateExist"), "", MessageBoxButton.OKCancel) == MessageBoxResult.OK;
                    }
                    if (save)
                    {
                        popForm.PopAlertDialogue(UILanguage.FindResource("TemplateSaving"), (object sender1, PopFormArg arg1) =>
                        {
                            PluginHandler.SavePluginAsTemplateToDisk(Config.CurrentPlugin, false);
                            Config.ProcesingPluginNameModel.Modified = false;
                            Thread.CurrentThread.Join(500);
                        });
                        PluginHandler.LoadAllTemplates();
                    }
                }
            }
            else
            {
                popForm.PopAlertDialogue(UILanguage.FindResource("TemplateSaving"), (object sender1, PopFormArg arg1) =>
                {
                    PluginHandler.SavePluginAsTemplateToDisk(Config.CurrentPlugin, false);
                    Config.ProcesingPluginNameModel.Modified = false;
                    Thread.CurrentThread.Join(500);
                });
                PluginHandler.LoadAllTemplates();
            }
        }

        private void menuItem_SaveTemplateAs_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();

            dlg.FileName = Config.CurrentTemplate.Container.Name;
            dlg.DefaultExt = ".cvt1";
            dlg.Filter = "Convertor Factory Template (.cvt1)|*.cvt1";
            if (dlg.ShowDialog() == true)
            {
                string filename = dlg.FileName;
                //Config.TemplateContainer.Name = filename;
                Config.CurrentTemplate.Container.Path = dlg.FileName;
                PluginHandler.SavePluginAsTemplateToDisk(Config.CurrentPlugin, false);
                PluginHandler.LoadAllTemplates();
            }
        }

        private void menuItem_OpenTemplate_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            //dlg.FileName = tempPluginsSavePath;
            dlg.DefaultExt = ".cvt1";
            dlg.Filter = "Convertor Factory Template (.cvt1)|*.cvt1";
            if (dlg.ShowDialog() == true)
            {
                string fileName = dlg.FileName;
                openTemplate(fileName, sender, e);
            }
        }

        private void menuItem_Setting_Click(object sender, RoutedEventArgs e)
        {
            tbInput.Focus();
            ConfigWindow b = new ConfigWindow();
            b.SetCenterOfWindow(this);
            b.ShowDialog();
        }

        private void menuItem_NewTemplate_Click(object sender, RoutedEventArgs e)
        {
            initTemplate();
        }

        private void initTemplate()
        {
            TemplateToSaveContainer temp = new TemplateToSaveContainer();

            var count = Config.GlobalConfig.TemplateList.Count(m => m.Name == temp.Name);
            while (count > 0)
            {
                temp = new TemplateToSaveContainer();
                count = Config.GlobalConfig.TemplateList.Count(m => m.Name == temp.Name);
            }
            Config.CurrentTemplate.Container = temp;
            Config.CurrentTemplate.Container.Path = Config.TempPluginsSavePath;
        }

        private void menuItem_ShowAbout_Click(object sender, RoutedEventArgs e)
        {
            AboutUs aboutus = new AboutUs();
            aboutus.SetCenterOfWindow(this);
            aboutus.ShowDialog();
        }

        private void menuItem_Help_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start(Config.HELP_URL);
        }

        private void menuItem_Example_Click(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Process.Start(Config.TEMPLATE_URL);
        }

        private void menuItem_CheckUpdate_Click(object sender, RoutedEventArgs e)
        {

            popForm.PopAlertDialogue(UILanguage.FindResource("Help_CheckingUpdate"),
                (object sender1, PopFormArg arg1) =>
                {
                    UpdateHandler update = new UpdateHandler();
                    update.CheckUpdate();
                },
                (object sender1, PopFormArg arg1) =>
                {
                    if (Config.GlobalConfig.HasUpdate)
                    {
                        if (MessageBox.Show(UILanguage.FindResource("Help_Update_Url").ToString(), "Update", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                        {
                            System.Diagnostics.Process.Start(Config.DOWNLOAD_URL);
                        }
                    }
                    else
                    {
                        MessageBox.Show(UILanguage.FindResource("Help_Update_No"), "Update", MessageBoxButton.OK);
                    }
                    BindingExpression be = cbTemplateType.GetBindingExpression(ComboBox.SelectedItemProperty);
                    if (be != null)
                    {
                        be.UpdateSource();
                    }
                });
        }

        #endregion

        #region Control Function

        private void btOutput_Click(object sender, RoutedEventArgs e)
        {
            if (btOutput.Text == UILanguage.FindResource("MenuOutput").ToString())
            {
                StartOutputThread();
            }
            else
            {
                stopOutputThread();
            }
        }

        private void tbInput_TextChanged(object sender, TextChangedEventArgs e)
        {
            TextBox tb = (TextBox)sender;
            if (Config.GlobalConfig.AutoOutput == true && tb.IsFocused && tb.Text.Length > 0)
            {
                btOutput_Click(btOutput, new RoutedEventArgs());
            }
        }

        private void lstTemplate_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            loadCurrentTemplate();
        }

        private void lstTemplate_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Delete)
            {
                menuItem_DeleteTemplate_Click(lstTemplate, e);
            }
        }

        private void lstTemplate_Drop(object sender, DragEventArgs e)
        {
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                if ((e.Effects & DragDropEffects.Copy) == DragDropEffects.Copy)
                {
                    String[] files = (String[])e.Data.GetData(DataFormats.FileDrop);

                    if (files.Length > 0)
                    {
                        foreach (string file in files)
                        {
                            openTemplate(file, sender, e);
                        }
                    }
                }
            }
        }

        private void lstTemplate_ContextMenuOpening(object sender, ContextMenuEventArgs e)
        {
            var targetData = ((ListBox)sender).SelectedItem;
            if (targetData == null)
            {
                menuItemTLoadTemplate.IsEnabled = false;
                menuItemTDeleteTemplate.IsEnabled = false;
                menuImteTRenameTemplate.IsEnabled = false;
            }
            else
            {
                menuItemTLoadTemplate.IsEnabled = true;
                menuItemTDeleteTemplate.IsEnabled = true;
                menuImteTRenameTemplate.IsEnabled = true;
            }
        }

        private void GridSplitter_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
        {
            Config.GlobalConfig.VerticalChange = GridInputOutput.RowDefinitions[0].ActualHeight;
            GridInputOutput.RowDefinitions[0].SetBinding(RowDefinition.HeightProperty, new Binding() { Source = Config.GlobalConfig, Path = new PropertyPath("VerticalChange") });
        }

        private void GridSplitter_Left_DragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
        {
            Config.GlobalConfig.LeftChange = gridLeft.ColumnDefinitions[0].ActualWidth;
            gridLeft.ColumnDefinitions[0].SetBinding(ColumnDefinition.WidthProperty, new Binding() { Source = Config.GlobalConfig, Path = new PropertyPath("LeftChange") });
        }

        private void Button_ClearLog_Click(object sender, RoutedEventArgs e)
        {
            Config.LogModel.Clear();
        }

        private void Button_SaveLog_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();

            dlg.FileName = Config.CurrentTemplate.Container.Name + "_log";
            dlg.DefaultExt = ".txt";
            dlg.Filter = "Text Log File (.txt)|*.txt";
            if (dlg.ShowDialog() == true)
            {
                string filename = dlg.FileName;
                try
                {
                    File.WriteAllText(filename, Config.LogModel.ToString());
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void Button_Page_Click(object sender, RoutedEventArgs e)
        {
            string text = ((Button)sender).Content.ToString();
            switch (text)
            {
                case "<<":
                    Config.LogModel.Page = 1;
                    break;
                case "<":
                    Config.LogModel.Page--;
                    break;
                case ">":
                    Config.LogModel.Page++;
                    break;
                case ">>":
                    Config.LogModel.Page = Config.LogModel.PageCount;
                    break;
            }
        }

        private void Button_PrevLogPage_Click(object sender, RoutedEventArgs e)
        {
            Config.LogModel.Page--;
        }

        private void Button_NextLogPage_Click(object sender, RoutedEventArgs e)
        {
            Config.LogModel.Page++;
        }

        private void AppErrorIcon_MouseDown(object sender, MouseButtonEventArgs e)
        {
            System.Diagnostics.Process.Start(Config.LogPath);
        }

        #endregion

        #region TemplateList ContextMenu Function

        private void menuItem_LoadTemplate_Click(object sender, RoutedEventArgs e)
        {
            loadCurrentTemplate();
        }

        private void menuItem_RenameTemplate_Click(object sender, RoutedEventArgs e)
        {
            if (lstTemplate.SelectedItem != null)
            {
                TemplateToLoadViewModel model = lstTemplate.SelectedItem as TemplateToLoadViewModel;

                bool reload = model.Path == Config.CurrentTemplate.Container.Path;

                TemplateToSaveContainer a = PluginHandler.LoaTemplateFromSerializeFile(model.Path);
                string oldPath = a.Path;
                RenameWindow re = new RenameWindow(a);
                if (re.ShowDialog() == true)
                {
                    try
                    {
                        PluginHandler.SaveTemplateToDisk(a, a.Path);
                        if (a.Path.ToLower() != oldPath.ToLower())
                        {
                            File.Delete(oldPath);
                        }
                        if (reload)
                        {
                            Config.CurrentTemplate.Container = PluginHandler.LoaTemplateFromSerializeFile(a.Path);
                        }
                    }
                    catch (Exception ex)
                    {
                        popForm.PopAlertMessage(ex.Message);
                        Log(this, ex.Message);
                    }
                    finally
                    {
                        PluginHandler.LoadAllTemplates();
                    }
                }
            }
        }

        private void menuItem_DeleteTemplate_Click(object sender, RoutedEventArgs e)
        {
            if (lstTemplate.SelectedItem != null)
            {
                if (MessageBox.Show(UILanguage.FindResource("DeleteTemplateConfirm"), "", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    TemplateToLoadViewModel a = (TemplateToLoadViewModel)lstTemplate.SelectedItem;
                    try
                    {
                        File.Delete(a.Path);
                    }
                    catch (Exception ex)
                    {
                        popForm.PopAlertMessage(ex.Message);
                        Log(this, ex.Message);
                    }
                    finally
                    {
                        PluginHandler.LoadAllTemplates();
                    }
                }
            }
        }

        private void menuItem_ChangeLanguage_Click(object sender, RoutedEventArgs e)
        {
            MenuItem m = sender as MenuItem;
            switch (m.Header.ToString())
            {
                case "中文":
                    Convertor.Plugin.Language.Change("zh-CN");
                    break;
                default:
                case "English":
                    Convertor.Plugin.Language.Change("en-us");
                    break;
                case "Français":
                    Convertor.Plugin.Language.Change("fr");
                    break;
            }
            PluginHandler.LoadPlugs();
            PluginHandler.LoadAllTemplates();

            //setPluginList();
            //loadTemplate();
        }

        #endregion

        #region Private Function

        private void outputFunc_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            progressBar1.Dispatcher.Invoke(() =>
            {
                progressBar1.Value += 1;
            });
        }

        private void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Config.LogModel.Update();
            Config.GlobalConfig.DurringTime = (DateTime.Now - convertDuringTime).TotalSeconds.ToString("f0");
        }

        private void checkUpdate()
        {
            if (Config.GlobalConfig.NeedUpdate)
            {
                UpdateHandler update = new UpdateHandler();
                update.HasUpdateEnvent += update_HasUpdateEnvent;
                update.StartCheckUpdate();
            }
        }

        private void update_HasUpdateEnvent(object sender, UpdateEventArg e)
        {
            if (e.HasUpdate)
            {
                if (MessageBox.Show(UILanguage.FindResource("Help_Update_Url").ToString(), "Update", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
                {
                    System.Diagnostics.Process.Start(Config.DOWNLOAD_URL);
                }
            }
        }

        private void loadArgs(object sender, RoutedEventArgs e)
        {
            if (Config.Args.Length > 0)
            {
                foreach (string s in Config.Args)
                {
                    openTemplate(s, sender, e);
                }
                Config.Args = new string[] { };
            }
        }

        private void loadInputText(string filename)
        {
            popForm.PopAlertDialogue(UILanguage.FindResource("LoadingInputText").ToString(),
                (object sender1, PopFormArg e1) =>
                {
                    try
                    {
                        Config.CurrentTemplate.Container.InputText = File.ReadAllText(filename, Encoding.Default);
                        tbInput.Dispatcher.Invoke(() => { tbInput.Text = Config.CurrentTemplate.Container.InputText; });
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                },
                null,
                null);
        }

        private void loadCurrentTemplate()
        {
            if (lstTemplate.SelectedItem != null)
            {
                Config.CurrentTemplate.Container = PluginHandler.LoaTemplateFromSerializeFile(((TemplateToLoadViewModel)lstTemplate.SelectedItem).Path);
                if (Config.CurrentTemplate != null)
                {
                    popForm.PopAlertMessage(UILanguage.FindResource("LoadTemplateSuccess").ToString(), true, 1000);
                    Config.ProcesingPluginNameModel.Modified = false;
                    tabRight.SelectedIndex = 1;
                    Config.GlobalConfig.ConvertedContent = null;
                }
            }
        }

        private void stopOutputThread()
        {
            Wpf.CommonTools.SystemExtension.MyThread.StopThread(threadOutput);
            toggleOutputButton("stop");
            stopProgressBar();
        }

        private void stopProgressBar()
        {
            progressBar1.Dispatcher.Invoke(() =>
            {
                progressBar1.Value = 0;
                progressBar1.Visibility = System.Windows.Visibility.Collapsed;
            });
        }


        private void startProgressBar()
        {
            progressBar1.Dispatcher.Invoke(() =>
            {
                progressBar1.Maximum = Config.CurrentPlugin.SelectedPlugins.Count + 1;
                progressBar1.Value = 1;
                progressBar1.Visibility = System.Windows.Visibility.Visible;
            });
        }

        private void toggleOutputButton(string stop)
        {
            if (stop == "stop")
            {
                btOutput.Dispatcher.Invoke(() =>
                {
                    btOutput.Text = UILanguage.FindResource("MenuOutput").ToString();
                    imgOutput.Source = new BitmapImage(new Uri(@"Images\Play.png", UriKind.Relative));
                });
                timer.Stop();
                stopProgressBar();
                Config.GlobalConfig.IsConvertingStop = true;
            }
            else
            {
                btOutput.Dispatcher.Invoke(() =>
                {
                    btOutput.Text = UILanguage.FindResource("MenuCancel").ToString();
                    imgOutput.Source = new BitmapImage(new Uri(@"Images\Pause.png", UriKind.Relative));
                });
                timer.Start();
                startProgressBar();
                Config.GlobalConfig.IsConvertingStop = false;
            }
        }

        private void output()
        {
            if (Config.CurrentPlugin.SelectedPlugins.Count == 0)
            {
                popForm.PopAlertMessage(UILanguage.FindResource("SelectMoreThanOnePlugin").ToString(), false);
                toggleOutputButton("stop");
                return;
            }

            convertDuringTime = DateTime.Now;
            IConvertParamters output = OutputFunc.OutputFunc(InputText, Config.CurrentPlugin.SelectedPlugins);

            Config.GlobalConfig.ConvertedContent = (output.OutputContent ?? "Object.NULL").ToString();
            Config.GlobalConfig.LastInputContent = (output.LastInputContent ?? "Object.NULL").ToString();

            if (Config.GlobalConfig.OutputToClipboard == true)
            {
                Clipboard.SetText(Config.GlobalConfig.ConvertedContent);
            }

            Config.ProcesingPluginNameModel.ProcessingPluginName = string.Empty;
            Config.LogModel.Update(true);

            popForm.PopAlertMessage(UILanguage.FindResource("OutputSucess").ToString());
            toggleOutputButton("stop");
            Config.GlobalConfig.DurringTime = (DateTime.Now - convertDuringTime).TotalSeconds.ToString("f3");
        }



        private void openTemplate(string fileName, object sender, RoutedEventArgs e)
        {
            if (fileName.EndsWith(".cvt1"))
            {
                Config.CurrentTemplate.Container = PluginHandler.LoaTemplateFromSerializeFile(fileName);
                if (MessageBox.Show(UILanguage.FindResource("TemplateImport"), "", MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    Config.CurrentTemplate.Container.Path = Config.TempPluginsSavePath;
                    menuItem_SaveToTempalte_Click(sender, e);
                    PluginHandler.LoadAllTemplates();
                }
                else
                {
                    Config.CurrentTemplate.Container = PluginHandler.LoaTemplateFromSerializeFile(fileName);
                }
            }
        }

        #endregion

        #region Pubilc Function

        public IConvertParamters InputText
        {
            get
            {
                string inputStr = Config.CurrentTemplate.Container.InputText ?? string.Empty;
                IConvertParamters content = new ConvertParamters(inputStr, inputStr);
                return content;
            }
        }

        public void Log(object sender, string log, LogTypes logType = LogTypes.Normal)
        {
            IPluginInfo info = sender as IPluginInfo;
            string name = info == null ? "System" : info.Name;
            if (Application.Current != null)
            {
                dataGridLog.Dispatcher.Invoke(() =>
                {
                    Config.LogModel.Add(new LogContent() { Date = DateTime.Now, Log = log, PluginName = name, LogType = logType });
                });
            }
        }

        public void StartOutputThread()
        {
            toggleOutputButton("start");

            Config.GlobalConfig.ConvertedContent = string.Empty;
            Config.GlobalConfig.DurringTime = "0";
            Config.LogModel.Clear();
            Config.LogModel.Update();

            Wpf.CommonTools.SystemExtension.MyThread.StopThread(threadOutput);

            threadOutput = new Thread(new ThreadStart(output));
            threadOutput.SetApartmentState(ApartmentState.STA);
            threadOutput.IsBackground = true;
            threadOutput.Start();

        }

        #endregion

        #region IPluginOutputHeler 成员

        public IConvertHelper OutputFunc { get; set; }

        #endregion


    }
}
